package com.lyncs.ods.modules.user.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.lyncs.ods.common.web.RequestHolder;
import com.lyncs.ods.constant.LyncsOdsConstant;
import com.lyncs.ods.modules.txn.model.TxnCommonInfo;
import com.lyncs.ods.modules.user.model.CompanyUserRelation;
import com.lyncs.ods.modules.user.mapper.CompanyUserRelationMapper;
import com.lyncs.ods.modules.user.model.UserInfo;
import com.lyncs.ods.modules.user.service.CompanyUserRelationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lyncs.ods.modules.user.service.UserInfoService;
import com.lyncs.ods.utils.TxnCommonUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 个人与公司关联关系表 服务实现类
 * </p>
 *
 * @author alex
 * @since 2022-02-15
 */
@Service
public class CompanyUserRelationServiceImpl extends ServiceImpl<CompanyUserRelationMapper, CompanyUserRelation> implements CompanyUserRelationService {

    @Autowired
    private UserInfoService userInfoService;

    @Override
    public String getLoginUserName() {
        CompanyUserRelation userRelation = this.lambdaQuery()
                .eq(CompanyUserRelation::getCompanyId, RequestHolder.getCompanyId())
                .eq(CompanyUserRelation::getUserId, RequestHolder.getUserId())
                .eq(CompanyUserRelation::getStatus, LyncsOdsConstant.BindStatus.BIND.getKey())
                .last("limit 1")
                .one();
        return userRelation == null ? null : userRelation.getNickname();
    }

    @Override
    public <T extends TxnCommonInfo> Map<String, String> getCompanyUserName(List<T> commonInfos) {
        LambdaQueryChainWrapper<CompanyUserRelation> lambdaQueryWrapper = this.lambdaQuery();
        for (TxnCommonInfo commonInfo : commonInfos) {
            lambdaQueryWrapper.or(wrapper -> wrapper.eq(CompanyUserRelation::getCompanyId, commonInfo.getCreatorCompanyId()).eq(CompanyUserRelation::getUserId, commonInfo.getCreator()));
        }
        List<CompanyUserRelation> companyUserRelations = lambdaQueryWrapper.list();
        return companyUserRelations.stream().collect(Collectors.toMap(TxnCommonUtils::buildCompanyUserKey, CompanyUserRelation::getNickname, (o1, o2) -> o1));
    }

    @Override
    public <T extends TxnCommonInfo> String getCompanyUserName(T commonInfo) {
        return getCompanyUserName(List.of(commonInfo)).values().stream().findFirst().orElse(null);
    }

    @Override
    public List<String> getCompanyUserEmail(Long companyId) {
        List<UserInfo> companyUserInfos = getCompanyUserInfos(List.of(companyId));
        return companyUserInfos.stream().map(UserInfo::getEmail).collect(Collectors.toList());
    }

    @Override
    public List<String> getCompanyUserPhone(Long companyId) {
        List<UserInfo> companyUserInfos = getCompanyUserInfos(List.of(companyId));
        return companyUserInfos.stream().map(UserInfo::getPhone).collect(Collectors.toList());
    }

    @Override
    public List<String> getCompanyUserEmail(List<Long> companyIds) {
        List<UserInfo> companyUserInfos = getCompanyUserInfos(companyIds);
        return companyUserInfos.stream().map(UserInfo::getEmail).collect(Collectors.toList());
    }

    @Override
    public List<String> getCompanyUserPhone(List<Long> companyIds) {
        List<UserInfo> companyUserInfos = getCompanyUserInfos(companyIds);
        return companyUserInfos.stream().map(UserInfo::getPhone).collect(Collectors.toList());
    }

    @Override
    public Map<Long, List<UserInfo>> getCompanyUserInfoMap(List<Long> companyIds) {
        Map<Long, List<UserInfo>> companyUserMap = new HashMap<>();
        List<CompanyUserRelation> companyUserRelations = this.lambdaQuery().in(CompanyUserRelation::getCompanyId, companyIds)
                .eq(CompanyUserRelation::getStatus, LyncsOdsConstant.BindStatus.BIND.getKey())
                .list();
        if (CollectionUtils.isEmpty(companyUserRelations)) {
            return companyUserMap;
        }
        Map<Long, List<Long>> companyUserIdMap = companyUserRelations.stream().collect(Collectors.groupingBy(CompanyUserRelation::getCompanyId, Collectors.mapping(CompanyUserRelation::getUserId, Collectors.toList())));
        List<Long> companyUserIds = companyUserRelations.stream().map(CompanyUserRelation::getUserId).distinct().collect(Collectors.toList());
        List<UserInfo> userInfos = this.userInfoService.lambdaQuery().in(UserInfo::getId, companyUserIds)
                .eq(UserInfo::getStatus, LyncsOdsConstant.UserStatus.ENABLE.getKey())
                .list();
        companyUserIdMap.forEach((companyId, userIds) -> {
            List<UserInfo> thisUserInfos = userInfos.stream().filter(u -> userIds.contains(u.getId())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(thisUserInfos)) {
                companyUserMap.put(companyId, thisUserInfos);
            }
        });
        return companyUserMap;
    }

    private List<UserInfo> getCompanyUserInfos(List<Long> companyIds) {
        Map<Long, List<UserInfo>> companyUserInfoMap = getCompanyUserInfoMap(companyIds);
        if (MapUtils.isEmpty(companyUserInfoMap)) {
            return List.of();
        }
        return companyUserInfoMap.values().stream().distinct().flatMap(Collection::stream).collect(Collectors.toList());
    }
}
